﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Web;

namespace System
{
    /// <summary>
    /// 通用调试方法
    /// </summary>
    public static class TongTestExpand
    {

        /// <summary>
        /// 测试此方法运行时间
        /// </summary>
        /// <param name="act">运行方法</param>
        /// <returns>返回时间单位毫秒</returns>
        public static long StopwatchRun(this Action act)
        {
            System.Diagnostics.Stopwatch sa = new System.Diagnostics.Stopwatch();
            long result = 0;
            sa.Restart();

            try
            {
                act();
            }
            finally
            {

                sa.Stop();
                result = sa.ElapsedMilliseconds;
            }
            return result;
        }


        public static long StopwatchCode(this Action action, out string msg)
        {


            // 2.
            GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
            int[] gcCounts = new int[GC.MaxGeneration + 1];
            for (int i = 0; i <= GC.MaxGeneration; i++)
            {
                gcCounts[i] = GC.CollectionCount(i);
            }

            // 3.
            Stopwatch watch = new Stopwatch();
            watch.Start();
            ulong cycleCount = GetCycleCount();
            action();
            ulong cpuCycles = GetCycleCount() - cycleCount;
            watch.Stop();



            string format = "运行时间 {0,-12}CPU时钟周期{1,-15},{2,-10} ,垃圾回收( 1代{3,-9} ,2代{4,-9} ,3代{5} )";
            object[] args = new object[6];
            args[0] = watch.ElapsedMilliseconds.ToString("N0") + "ms";
            args[1] = cpuCycles.ToString("N0");
            args[2] = "";
            if (GC.MaxGeneration >= 0) args[3] = GC.CollectionCount(0) - gcCounts[0];
            if (GC.MaxGeneration >= 1) args[4] = GC.CollectionCount(1) - gcCounts[1];
            if (GC.MaxGeneration >= 2) args[5] = GC.CollectionCount(2) - gcCounts[2];
            msg = string.Format(format, args);
            Console.WriteLine(msg);

            Console.WriteLine();
            return watch.ElapsedMilliseconds;
        }


        [DllImport("kernel32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool QueryThreadCycleTime(IntPtr threadHandle, ref ulong cycleTime);

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetCurrentThread();

        private static ulong GetCycleCount()
        {
            ulong cycleCount = 0;
            QueryThreadCycleTime(GetCurrentThread(), ref cycleCount);
            return cycleCount;
        }

    }
}